;(function () {})()
// 模板字符串插槽中传入联合类型的自动分发特性时，你可能会想到我们此前接触的一个能够生成联合类型的工具：索引类型查询操作符 keyof。基于 keyof + 模板字符串类型，我们可以基于已有的对象类型来实现精确到字面量的类型推导：
type Job = Array<string>
interface Foo {
  name: string
  age: number
  job: Job
}

type ChangeListener = {
  on: (change: `${keyof Foo}Changed`) => void
}
declare let listener: ChangeListener
// 提示并约束为 "nameChanged" | "ageChanged" | "jobChanged"
listener = { on: (changeType) => console.log(changeType) }
listener.on('ageChanged')

//TS 在引入模板字符串类型时支持了一个叫做 重映射（Remapping） 的新语法，基于模板字符串类型与重映射，我们可以实现一个此前无法想象的新功能：在映射键名时基于原键名做修改。
//我们可以使用映射类型很容易复制一个接口：
type Copy<T extends object> = {
  [K in keyof T]: T[K]
}
//然而，如果我们想要在复制时小小的修改下键名要怎么做？比如从 name 到 modified_name ？修改键值类型我们都很熟练了，但要修改键名，我们就需要本节的新朋友搭把手才可以。我们直接看如何基于重映射来修改键名：

type CopyWithRename<T extends object> = {
  [K in keyof T as `modified_${string & K}`]: T[K]
}
interface Foo2 {
  name: string
  age: number
}
type CopiedFoo = CopyWithRename<Foo2>
